import { provide, reactive, ref, watch } from 'vue'
import { map, remove } from 'lodash'
import { useI18n } from 'vue-i18n'
import { I18nMessageId, ObjectType, ResponseDataPromise } from 'typings/interfaces'
import { OperateTypes } from '@/enums/operateTypes'
import { $Keys } from 'typings/util'
import { fnFormatting } from '@/utils/formatting.js'
import { ElMessage } from 'element-plus'

/**
 * 表单 hooks
 * @param form 表单值
 * @param updateData 更新数据
 * @param handleInitialValues 处理预设值
 */

function useForm<T extends ObjectType>(
  form: T,
  updateData: () => any,
  handleInitialValues = (value: ObjectType) => value
) {
  type Keys = $Keys<typeof form>
  const { t } = useI18n()
  const validateList = reactive<any>([])
  const visible = ref<boolean>(false)
  const title = ref<string>('')
  const initialValues = ref<Record<Keys, any> | ObjectType>({})
  const disabled = ref(false)
  const params = ref<ObjectType>(form)
  const operateType = ref<OperateTypes | null>(null)
  const addValidate = (validate: any) => validateList.push(validate)
  const validate = () => {
    return new Promise((resolve, reject) => {
      Promise.all(map(validateList, (validate) => validate()))
        .then(() => resolve(true))
        .catch((e) => {
          ElMessage.error('校验失败，请填写必填数据后再提交')
          reject(false)
        })
    })
  }
  // 依赖注入
  /** 添加校验规则 */
  provide('AddValidate', addValidate)

  /**
   * 控制表单禁用状态
   * @param type 操作类型
   * @returns boolean
   */
  const handleDisabled = (type: OperateTypes) => {
    if (
      type === OperateTypes.APPROVAL ||
      type === OperateTypes.VIEW ||
      type === OperateTypes.REPORT
    ) {
      return (disabled.value = true)
    }
    return (disabled.value = false)
  }

  const handleParams = (type: OperateTypes, initialValues: ObjectType) => {
    if (type === OperateTypes.ADD) {
      params.value = {
        ...form,
        ...initialValues,
      }
    } else {
      params.value = initialValues
    }
  }

  const action = (type: OperateTypes, titleId: I18nMessageId, initValues: ObjectType) => {
    initValues = handleStake(initValues)
    operateType.value = type
    initialValues.value = handleInitialValues(initValues)
    title.value = t(titleId)
    visible.value = true
    handleParams(type, initialValues.value)
    handleDisabled(type)
  }
  const handleStake = (initValues) => {
    if (initValues.startStake) {
      initValues.startStake = fnFormatting(initValues?.startStake)
    }
    if (initValues.endStake) {
      initValues.endStake = fnFormatting(initValues?.endStake)
    }
    if (initValues.centerStake) {
      initValues.centerStake = fnFormatting(initValues?.centerStake)
    }
    return initValues
  }

  /* 请求数据 */
  const request = (fn: () => ResponseDataPromise<any>) => {
    validate()
      .then(() => fn())
      .then(() => {
        visible.value = false
        updateData()
      })
  }

  const onClose = () => {visible.value = false;updateData()}

  // 重置
  watch(visible, (newValue: boolean) => {
    if (!newValue) {
      remove(validateList, () => true)
      initialValues.value = {}
      params.value = {}
    }
  })

  return {
    validate,
    visible,
    title,
    initialValues,
    params,
    operateType,
    action,
    request,
    onClose,
    disabled,
  }
}

export default useForm
